﻿using System;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Input;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using GalaSoft.MvvmLight.Threading;
using LiSAClient.Core.Messages;
using LiSAClient.Core.Models;
using LiSAClient.Core.Services;
using LiSAClient.Core.Services.Factories;
using LiSAClient.Core.Viewmodel;
using LiSAClient.LiSAService;
using LiSAClient.WpfClient.ViewModel.Projects.Edit;
using Microsoft.Win32;

namespace LiSAClient.WpfClient.ViewModel.Projects
{
    class ProjectDetailsViewModel : ContentViewModel
    {
        #region Observable Objects
        private Guid projectID { get; set; }

        private Project project;
        public Project Project
        {
            get
            {
                return this.project;
            }

            set
            {
                this.Set(() => this.Project, ref this.project, value);
            }
        }

        private string bibTexString;
        public string BibTexString
        {
            get
            {
                return this.bibTexString;
            }

            set
            {
                this.Set(() => this.BibTexString, ref this.bibTexString, value);
            }
        }

        public ICommand AddBibtexString { get; private set; }
        public ICommand WorkOnProjectCmd { get; private set; }
        public ICommand RemoveBadArticles { get; private set; }
        public ICommand ViewStageResults { get; private set; }
        public ICommand AddBibtexFile { get; private set; }
        public ICommand DownloadBibtexFile { get; private set; }
        public ICommand GenerateReport { get; private set; }
        public ICommand GenerateFullReport { get; private set; }
        public ICommand EditProjectMetainformation { get; private set; }
        public ICommand EditProjectMembers { get; private set; }
        public ICommand EditProjectCriteria { get; private set; }
        public ICommand EditProjectSearchStrings { get; private set; }
        public ICommand EditProjectSearchKeywords { get; private set; }
        public ICommand EditProjectQuestions { get; private set; }
        public ICommand EditProjectStages { get; private set; }
        
        #endregion

        #region Initializers
        /// <summary>
        /// Initializes the viewmodels properties
        /// </summary>
        /// <param name="projectID">ID of the project to show information for</param>
        public ProjectDetailsViewModel(Guid projectID)
        {
            this.projectID = projectID;
            this.Project = new Project();
            this.BibTexString = string.Empty;
            this.AddBibtexString = new RelayCommand(this.DoAddBibtexString);
            this.WorkOnProjectCmd = new RelayCommand(this.DoWorkOnProject);
            this.RemoveBadArticles = new RelayCommand(this.DoRemoveBadArticles);
            this.ViewStageResults = new RelayCommand(this.DoViewStageResults);
            this.AddBibtexFile = new RelayCommand(this.DoAddBibtexFile);
            this.DownloadBibtexFile = new RelayCommand(this.DoDownloadBibtexFile);
            this.GenerateReport = new RelayCommand(this.DoGenerateReport);
            this.EditProjectMetainformation = new RelayCommand(this.DoEditProjectMetainformation);
            this.GenerateFullReport = new RelayCommand(this.DoGenerateFullReport);
            this.EditProjectMembers = new RelayCommand(this.DoEditProjectMembers);
            this.EditProjectCriteria = new RelayCommand(this.DoEditProjectCriteria);
            this.EditProjectSearchStrings = new RelayCommand(this.DoEditProjectSearchStrings);
            this.EditProjectSearchKeywords = new RelayCommand(this.DoEditProjectSearchKeywords);
            this.EditProjectQuestions = new RelayCommand(this.DoEditProjectQuestions);
            this.EditProjectStages = new RelayCommand(this.DoEditProjectStages);
        }

        /// <summary>
        /// Retrieves the information needed
        /// </summary>
        public override void OnPresented()
        {
            this.Presenter.StartWaiting("Fetching project information...");
            Task.Factory.StartNew(
                () =>
                {
                    this.Project = ServiceFactory.Instance.Get<ProjectService>().GetProjectByID(this.projectID);
                    this.Presenter.FinishedWaiting();
                });
        }
        #endregion

        #region Methods
        /// <summary>
        /// Open the work-window
        /// </summary>
        private void DoWorkOnProject()
        {
            DispatcherHelper.CheckBeginInvokeOnUI(() =>
            {
                try
                {
                    this.Presenter.PresentContent(new WorkOnProjectViewModel(this.projectID) { ShowInWindow = true });
                }
                catch (Exception exc)
                {
                    //ARGH
                }
            });
        }

        /// <summary>
        /// Open the overall progress window
        /// </summary>
        private void DoViewStageResults()
        {
            DispatcherHelper.CheckBeginInvokeOnUI(() =>
            {
                this.Presenter.PresentContent(new ProjectAdminProgressViewViewModel(this.projectID));
            });
        }

        /// <summary>
        /// Method to send a bibtex string to the server for parsing
        /// </summary>
        private void DoAddBibtexString()
        {
            ServiceFactory.Instance.Get<ProjectService>().AddBibtexToProject(this.BibTexString, this.projectID);
            this.BibTexString = string.Empty;

            Messenger.Default.Send(new ShowNotificationMessage
            {
                NotificationType = NotificationType.Info,
                Header = "Task complete!",
                Body = "The BibTex information has been sent to the server and is being parsed."
            });
        }
        
        /// <summary>
        /// Method to send a bibtex string to the server for parsing
        /// </summary>
        private async void DoAddBibtexFile()
        {
            string location;
            // Open the openfil dialog
            var dlg = new Microsoft.Win32.OpenFileDialog
            {
                DefaultExt = ".bib", 
                Filter = "BibTex Files (*.bib)|*.bib"
            };

            var result = dlg.ShowDialog();
            if (result == true)
            {
                location = dlg.FileName;
            }
            else
            {
                // Nothing selected or error. Return to end it all.
                return;
            }

            // Get the contents of the bibtex file and send them to the server
            try
            {
                string bibtexString;
                using (var sr = new StreamReader(location))
                {
                    bibtexString = await sr.ReadToEndAsync();
                }
                ServiceFactory.Instance.Get<ProjectService>().AddBibtexToProject(bibtexString, this.projectID);

                Messenger.Default.Send(new ShowNotificationMessage
                {
                    NotificationType = NotificationType.Info,
                    Header = "Task complete!",
                    Body = "The BibTex information has been sent to the server and is being parsed."
                });
            }
            catch (Exception ex)
            {
                Messenger.Default.Send(new ShowNotificationMessage
                {
                    NotificationType = NotificationType.Error,
                    Header = "Error!",
                    Body = "The BibTex file could not be read. Error" + ex.Message
                });
            }
        }

        /// <summary>
        /// Get a BibTex representation of all articles on project and save via Savefile dialogue
        /// </summary>
        private void DoDownloadBibtexFile()
        {
            // Find a savelocation
            var reportString = ServiceFactory.Instance.Get<ProjectService>().GetArticlesAsBibtex(this.projectID);
            var saveFileDialog1 = new SaveFileDialog();
            saveFileDialog1.InitialDirectory = Convert.ToString(Environment.SpecialFolder.MyDocuments);
            saveFileDialog1.Filter = "BibTex file (*.BIB)|*.bib|All Files (*.*)|*.*";
            saveFileDialog1.FilterIndex = 1;

            if (saveFileDialog1.ShowDialog() == true)
            {
                File.WriteAllText(saveFileDialog1.FileName, reportString);
            }
        }

        /// <summary>
        /// Filter out articles in the project that have a majority vote saying they're OUT
        /// </summary>
        private void DoRemoveBadArticles()
        {
            ServiceFactory.Instance.Get<ProjectService>().RemoveBadArticles(this.Project.ProjectID);
        }

        /// <summary>
        /// Generates a meta report for the project
        /// </summary>
        private void DoGenerateReport()
        {
            var reportString = ServiceFactory.Instance.Get<ReportService>().GetProjectMetadataReport(this.Project.ProjectID);
            var saveFileDialog1 = new SaveFileDialog();
            saveFileDialog1.InitialDirectory = Convert.ToString(Environment.SpecialFolder.MyDocuments);
            saveFileDialog1.Filter = "Comma separated file (*.CSV)|*.csv|All Files (*.*)|*.*";
            saveFileDialog1.FilterIndex = 1;

            if (saveFileDialog1.ShowDialog() == true)
            {
                File.WriteAllText(saveFileDialog1.FileName, reportString);
            }
        }

        /// <summary>
        /// Generates a full report for the project
        /// </summary>
        private void DoGenerateFullReport()
        {
            var reportString = ServiceFactory.Instance.Get<ReportService>().GetFullProjectReport(this.Project.ProjectID);
            var saveFileDialog1 = new SaveFileDialog();
            saveFileDialog1.InitialDirectory = Convert.ToString(Environment.SpecialFolder.MyDocuments);
            saveFileDialog1.Filter = "Comma separated file (*.CSV)|*.csv|All Files (*.*)|*.*";
            saveFileDialog1.FilterIndex = 1;

            if (saveFileDialog1.ShowDialog() == true)
            {
                File.WriteAllText(saveFileDialog1.FileName, reportString);
            }
        }

        /// <summary>
        /// Opens a window for editing the project metainformation
        /// </summary>
        public void DoEditProjectMetainformation()
        {
            DispatcherHelper.CheckBeginInvokeOnUI(() =>
            {
                this.Presenter.PresentContent(new EditMetainformationViewModel(this.Project) { ShowInWindow = true });
            });
        }

        /// <summary>
        /// Opens a window for editing the project members
        /// </summary>
        public void DoEditProjectMembers()
        {
            DispatcherHelper.CheckBeginInvokeOnUI(() =>
            {
                this.Presenter.PresentContent(new EditMembersViewModel(this.Project) { ShowInWindow = true });
            });
        }

        /// <summary>
        /// Opens a window for editing the project SearchStrings
        /// </summary>
        public void DoEditProjectSearchStrings()
        {
            DispatcherHelper.CheckBeginInvokeOnUI(() =>
            {
                this.Presenter.PresentContent(new EditSearchstringsViewModel(this.Project) { ShowInWindow = true });
            });
        }

        /// <summary>
        /// Opens a window for editing the project Criteria
        /// </summary>
        public void DoEditProjectCriteria()
        {
            DispatcherHelper.CheckBeginInvokeOnUI(() =>
            {
                this.Presenter.PresentContent(new EditCriteriaViewModel(this.Project) { ShowInWindow = true });
            });
        }

        /// <summary>
        /// Opens a window for editing the project Keywords
        /// </summary>
        public void DoEditProjectSearchKeywords()
        {
            DispatcherHelper.CheckBeginInvokeOnUI(() =>
            {
                this.Presenter.PresentContent(new EditKeywordsViewModel(this.Project) { ShowInWindow = true });
            });
        }

        /// <summary>
        /// Opens a window for editing the project Questions
        /// </summary>
        public void DoEditProjectQuestions()
        {
            DispatcherHelper.CheckBeginInvokeOnUI(() =>
            {
                this.Presenter.PresentContent(new EditQuestionsViewModel(this.Project) { ShowInWindow = true });
            });
        }
        
        /// <summary>
        /// Opens a window for editing the project Stages
        /// </summary>
        public void DoEditProjectStages()
        {
            DispatcherHelper.CheckBeginInvokeOnUI(() =>
            {
                this.Presenter.PresentContent(new EditStagesViewModel(this.Project) { ShowInWindow = true });
            });
        }
        #endregion
    }
}
